﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Detective.Components.Base;
using Detective.Game.Gamepad.Base;
using Detective.World;

namespace Detective.Game.Gamepad
{
    public class Keyboard : BaseComponent, IKeyObserved, IDisposable
    {
        #region Fields

        private List<IKeyObserved> 
            _observedList = new List<IKeyObserved>();

        private List<Keys>
            _hookedKeys = new List<Keys>();

        #endregion

        #region Constructors and Dispose

        public Keyboard()
        {
            _hookedKeys.Add(Keys.Escape);
            _hookedKeys.Add(Keys.Left);
            _hookedKeys.Add(Keys.Right);

            _hookedKeys.Add(Keys.D1);
            _hookedKeys.Add(Keys.D2);
            _hookedKeys.Add(Keys.D3);
            _hookedKeys.Add(Keys.D4);
            _hookedKeys.Add(Keys.D5);
            _hookedKeys.Add(Keys.D6);
            _hookedKeys.Add(Keys.D7);

            _hookedKeys.Add(Keys.NumPad0);
            _hookedKeys.Add(Keys.NumPad1);
        }

        public void Dispose()
        {
        }

        #endregion

        [DllImport("user32.dll")]
        private static extern short GetKeyState(int nVirtKey);

        #region Public methods

        public void AddObserved(IKeyObserved observed)
        {
            _observedList.Add(observed);
        }

        public void OnKeyDown(KeyEventArgs arg)
        {
            for (int i = 0; i < _observedList.Count; i++)
            {
                _observedList[i].OnKeyDown(arg);
            }
        }

        public void OnKeyUp(KeyEventArgs arg)
        {
            for (int i = 0; i < _observedList.Count; i++)
            {
                _observedList[i].OnKeyUp(arg);
            }
        }

        #endregion

        public override int GetDelayMilliSeconds()
        {
            return 10;
        }

        protected override void OnDelay(GameTime gameTime)
        {
            for (int i = 0; i < _hookedKeys.Count; i++)
            {
                switch (GetKeyState((int)_hookedKeys[i]))
                {
                    case 0:
                        // Not pressed and not toggled on.
                        break;

                    case 1:
                        // Not pressed, but toggled on
                        OnKeyUp(new KeyEventArgs(_hookedKeys[i]));
                        break;

                    default:
                        // Pressed (and may be toggled on)
                        OnKeyDown(new KeyEventArgs(_hookedKeys[i]));
                        break;
                }
            }
        }
    }
}